//
//  STDSPainterHairEffect.h
//  STDSRenderSDKIOS
//
//  Created by 陈学明 on 2023/8/10.
//

#ifndef STDSPainterHairEffect_h
#define STDSPainterHairEffect_h

#include "STDSBaseEffect.hpp"

class STDSPainterHairEffect: public STDSBaseEffect {
public:
    STDSPainterHairEffect() {
        mEffectType = STDSEffectTypeHairPainter;
    }
    ~STDSPainterHairEffect() {
//        printf("dealloc--STDSMosaicEffect\n");
    }
    
    void initGL() override {
        STDSBaseEffect::initGL();
    }
    
    void setFloatArguments(const char *name, float *floatValue, int n) override {
        if (strcmp(name, "mIntencity") == 0) {
            mIntencity = *floatValue;
        }
    }
    
    void setStringArtuments(const char *name, const char *stringValue) override {
        if (strcmp(name, "mask") == 0) {
            auto mask_path = std::string(stringValue);
            this->mContext->autoRelease(this->mMask);
            this->mMask = this->mContext->getImageTexture(mask_path);
        } else if (strcmp(name, "color") == 0) {
            auto color_path = std::string(stringValue);
            this->mContext->autoRelease(this->mColor);
            this->mColor = this->mContext->getImageTexture(color_path);
        }
    }
    
    void setBitmapArguments(const char *name, const char *data, int width, int height) override {
        if (strcmp(name, "mask") == 0) {
            this->mMask = make_shared<STDSTexture>((const unsigned char *)data, width, height);
        } else if (strcmp(name, "color") == 0) {
            this->mColor = make_shared<STDSTexture>((const unsigned char *)data, width, height);
        }
    }
    
public:
    shared_ptr<STDSShaderProgram> getBlendEffectProgram() {
        if (mBlendProgram == nullptr) {
            mBlendProgram = mContext->getProgram(kShaderSRCBlendSoftLight);
        }
        return mBlendProgram;
    }

    shared_ptr<STDSShaderProgram> getMaskKeyProgram() {
        if (mMaskkeyProgram == nullptr) {
            mMaskkeyProgram = mContext->getProgram(kShaderSRCMaskKey);
        }
        return mMaskkeyProgram;
    }
    
    void draw() override {
        auto keyProgram = getMaskKeyProgram();
        auto blendProgram = getBlendEffectProgram();
        if (blendProgram == nullptr || mTexture == nullptr || keyProgram== nullptr) {
            return;
        }
        if (mColor == nullptr || mMask == nullptr) {
            drawTexture(mTexture->getId());
            return;
        }

        auto hairfbo = make_shared<STDSRenderTarget>(mSizeSRC.x, mSizeSRC.y);
        hairfbo->bindSelf();

        keyProgram->use();
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, mColor->getId());
        keyProgram->setUniform(keyProgram->getUniform("uTexture"), 0);

        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, mMask->getId());
        keyProgram->setUniform(keyProgram->getUniform("uMask"), 1);

        mAtbRect.setPosVex(keyProgram->getAttrib("aPos"));
        mAtbRect.setPosTex(keyProgram->getAttrib("aTexCoord"));
        mAtbRect.draw();
        keyProgram->unuse();
        hairfbo->restore();

        blendProgram->use();
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, hairfbo->getTexId());
        blendProgram->setUniform(blendProgram->getUniform("uTexture2"), 0);

        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, mTexture->getId());
        blendProgram->setUniform(blendProgram->getUniform("uTexture"), 1);
        blendProgram->setUniform(blendProgram->getUniform("uParam"), mIntencity);

        mAtbRect.setPosVex(blendProgram->getAttrib("aPos"));
        mAtbRect.setPosTex(blendProgram->getAttrib("aTexCoord"));
        mAtbRect.draw();
        blendProgram->unuse();
    }

private:
    shared_ptr<STDSTexture> mColor{nullptr}; // mask
    shared_ptr<STDSTexture> mMask{nullptr}; // mask
    float mIntencity{1.0}; // 强度,0.0~1.0
    shared_ptr<STDSShaderProgram> mMaskkeyProgram{nullptr};
    shared_ptr<STDSShaderProgram> mBlendProgram{nullptr};
};

#endif /* STDSPainterHairEffect_h */
